package com.eian.boot.rabbit.core.sender;

import com.eian.boot.common.id.IdHelper;
import com.eian.boot.rabbit.config.RabbitPropertiesExt;
import com.eian.boot.rabbit.model.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class RabbitTemplateProxy {

    private final RabbitTemplate rabbitTemplate;
    private final RabbitPropertiesExt properties;

    public RabbitTemplateProxy(RabbitTemplate rabbitTemplate, RabbitPropertiesExt properties) {
        this.rabbitTemplate = rabbitTemplate;
        this.properties = properties;
    }

    @Retryable(
            retryFor = {Exception.class},
            maxAttemptsExpression = "#{@rabbitPropertiesExt.retry().maxAttempts()}",
            backoff = @Backoff(delayExpression = "#{@rabbitPropertiesExt.retry().backoffMs()}")
    )
    public void send(String exchange, String routingKey, Object payload) {
        CorrelationData correlationData = new CorrelationData(IdHelper.simpleUuid());

        if (payload instanceof Message<?> unified) {
            sendUnifiedMessage(exchange, routingKey, unified.incrementRetryCount(), correlationData);
        } else {
            rabbitTemplate.convertAndSend(exchange, routingKey, payload, correlationData);
            log.debug("消息已发送: [ Exchange: {}, routingKey: {}, payload: {}, correlationData:{} ]",
                    exchange, routingKey, payload, correlationData);
        }
    }

    private void sendUnifiedMessage(String exchange, String routingKey,
                                    Message<?> message,
                                    CorrelationData correlationData) {
        MessagePostProcessor processor = msg -> {
            if (message.deliveryTime() != null) {
                long delay = message.deliveryTime() - System.currentTimeMillis();
                msg.getMessageProperties().setDelayLong(Math.max(delay, 0));
            }
            msg.getMessageProperties().setMessageId(correlationData.getId());
            msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
            return msg;
        };

        rabbitTemplate.convertAndSend(exchange, routingKey, message, processor, correlationData);
        log.debug("消息已发送: [ Exchange: {}, routingKey: {}, message: {}, correlationData:{} ]",
                exchange, routingKey, message, correlationData);
    }
}